from euca2ools import Euca2ool, InstanceValidationError, Util
import logging
log = logging.getLogger(__name__)

from crv.model.crvmodel import *
from crv.model.rp import *

from sqlalchemy.orm import mapper
from sqlalchemy.orm import relation, backref

import sys,os
from subprocess import Popen,PIPE

class EucaVMMaker(VMMaker):
    """
    This is the maker that start/stops VM in eucalyptus cloud
 
    @author Yushu Yao
    @version 0.1
    """

    def debug(self,str):
        #        self.debug(str)
        log.debug(str)

    def __new__(cls, *args, **kwds):
#        print "EucaVMMaker.__new__", args, kwds
        cls.__initialized=False
        return VMMaker.__new__(cls, *args, **kwds)
  
    def __init__(self,name="DummyEucaVMMaker"):
        #        import pdb; pdb.set_trace()            
        super(EucaVMMaker, self).__init__("euca")
        
        self.setAttr("name",name)
        self.__initialized=False

        self.debug("EucaVMMaker::__init__(%s)"%(self.getAttr("vmtype")))

    def ready(self):
        if not self.__initialized:
            self.__doInit()
            
        return True

    def __doInit(self):
        if self.__initialized:
            return

        self.__euca=Euca2ool()
        self.__euca.ec2_user_secret_key=self.getAttr('EC2_SECRET_KEY')
        self.__euca.ec2_user_access_key=self.getAttr("EC2_ACCESS_KEY")
        self.__euca.ec2_url=self.getAttr("EC2_URL")

        self.__initialized=True
        
    def __callDescribe(self,idlist=[]):
        self.debug("EucaVMMaker:__callDescribe called, idlist=%s"%str(idlist))

        if not self.__initialized:
            self.__doInit()

        instance_ids = idlist
        try:
            for id in instance_ids:
                self.__euca.validate_instance_id(id)
        except InstanceValidationError:
            raise RuntimeError('Invalid instance id')

        euca_conn = self.__euca.make_connection()
        try:
            reservations = euca_conn.get_all_instances(instance_ids)
        except Exception, ex:
            raise RuntimeError('%s' % ex)

        check_instance_ids = False
        if(len(instance_ids) > 0):
            check_instance_ids = True
            
        instances={}
        
        for reservation in reservations:
            for instance in reservation.instances:
                if check_instance_ids:
                    if instance.id in instance_ids:
                        instances[instance.id]=instance
                else:
                    instances[instance.id]=instance

        return instances

    def isStopping(self,identifier):
        if not self.__initialized:
            self.__doInit()

        if identifier==None:
            return False
        ins=self.__callDescribe([identifier])
        return ins.has_key(identifier) and ins[identifier].state=="shutting-down"
    
    def isStarting(self,identifier):
        if not self.__initialized:
            self.__doInit()

        if identifier==None:
            return False
        ins=self.__callDescribe([identifier])
        
        if ins.has_key(identifier):
            log.debug("EucaVMMaker::isStarting::ins[identifier].state=%s"%str(ins[identifier].state))

        return ins.has_key(identifier) and ins[identifier].state=="pending"
    #ins[identifier].state!="shutting-down"  and ins[identifier].state!="terminated"  and ins[identifier].state!="running"

    def isStopped(self,identifier):

        if not self.__initialized:
            self.__doInit()

        if identifier==None:
            return True
        ins=self.__callDescribe([identifier])
        return not ins.has_key(identifier) or (ins.has_key(identifier) and ins[identifier].state=="terminated")

    def getStatus(self,identifier):
        if not self.__initialized:
            self.__doInit()
        if identifier==None:
            return "UNDEFINED"
        ins=self.__callDescribe([identifier])
        if ins.has_key(identifier):
            return ins[identifier].state
        return "UNDEFINED"

    def isStarted(self,identifier):
        if not self.__initialized:
            self.__doInit()

        if identifier==None:
            return False
        ins=self.__callDescribe([identifier])
        return ins.has_key(identifier) and ins[identifier].state=="running"
            
    def getIdentifiers(self):
        if not self.__initialized:
            self.__doInit()

        self.debug("EucaVMMaker:getIdentifiers called")
        instances=self.__callDescribe()        
        return instances.keys()

    def powerOn(self,userdatafile=None):

        self.debug("EucaVMMaker:poweronVM called")
        if not self.__initialized:
            self.__doInit()

#        image_id = 'emi-7AD2165B'
#        keyname = 'mykey'
#        kernel_id = 'eki-7A1F1651'
#        ramdisk_id = 'eri-571515B5'
#        min_count = 1
#        max_count = 1
#        instance_type = 'm1.small' 
#        group_names = ['at3'] 
#        user_data = None
#        addressing_type = None
        #        zone = None


        image_id = self.getAttr("image_id")
        keyname = self.getAttr("keyname")
        kernel_id = self.getAttr("kernel_id")
        ramdisk_id = self.getAttr("ramdisk_id")
        min_count = 1
        max_count = 1
        instance_type = self.getAttr("instance_type")
        group_names = self.getAttr("group_names").split(',')
        addressing_type = self.getAttr("addressing_type")
        user_data = None
        zone = None

        #read userdata
        if userdatafile!=None:
            USER_DATA_CHUNK_SIZE = 512
            user_data = "";
            user_data_file = open(userdatafile, "r")
            while 1:
                data = user_data_file.read(USER_DATA_CHUNK_SIZE)
                if not data:
                    break
                user_data += data
            user_data_file.close()
        
        euca_conn = self.__euca.make_connection()
	try:
            logstr="euca_conn.run_instances(image_id = '%s', min_count = %d, max_count = %d, key_name = '%s', security_groups = %s,  addressing_type = '%s', instance_type = '%s', placement = %s, kernel_id = '%s', ramdisk_id = '%s',user_data = '%s')"%(image_id,min_count,max_count,keyname,group_names,addressing_type,instance_type,zone,kernel_id,ramdisk_id,user_data)
            self.debug("Length Logstr=%d, logstr=%s"%(len(logstr),logstr))

            reservation=eval(logstr)
            ouf=open("/tmp/makeeuca_%s.txt"%str(reservation),"w")
            ouf.write(logstr)
            ouf.close()

            """
            reservation = euca_conn.run_instances(image_id = image_id,
                                                  min_count = min_count,
                                                  max_count = max_count,
                                                  key_name = keyname,
                                                  security_groups = group_names,
                                                  addressing_type = addressing_type,
                                                  instance_type = instance_type,
                                                  placement = zone,
                                                  kernel_id = kernel_id,
                                                  ramdisk_id = ramdisk_id,
                                                  user_data = user_data
                                                  )
                                                  """
        except Exception, ex:
            raise RuntimeError('%s' % str(ex))

        self.debug("EucaVMMaker:poweronVM: reservation=%s instance=%s"%(reservation.id,reservation.instances[0].id))
        
        return reservation.instances[0].id

    def powerOff(self,identifier):
        if not self.__initialized:
            self.__doInit()

        self.debug("EucaVMMaker:poweroffVM called: identifier=%s"%str(identifier))
        euca_conn = self.__euca.make_connection()
	try:
            instances = euca_conn.terminate_instances([identifier])
        except Exception, ex:
            raise RuntimeError('%s' % ex)

        



